package org.eu.hdeogratias.license.operation;

import de.schlichtherle.license.*;
import org.eu.hdeogratias.license.manager.CustomKeyStoreParam;
import org.eu.hdeogratias.license.manager.CustomLicenseManager;
import org.eu.hdeogratias.license.server.LinuxServer;
import org.eu.hdeogratias.license.server.Server;
import org.eu.hdeogratias.license.server.WindowsServer;
import org.eu.hdeogratias.license.toolkit.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.prefs.Preferences;

/**
 * 许可证验证
 *
 * @author weitao
 */
public class LicenseVerify {
    private final static Logger logger = LoggerFactory.getLogger(LicenseVerify.class);
    /**
     * 证书subject
     */
    private final String subject;
    /**
     * 公钥别称
     */
    private final String publicAlias;
    /**
     * 访问公钥库的密码
     */
    private final String storePass;
    /**
     * 证书生成路径
     */
    private final String licensePath;
    /**
     * 密钥库存储路径
     */
    private final String publicKeysStorePath;
    /**
     * LicenseManager
     */
    private LicenseManager licenseManager;
    /**
     * 证书是否安装成功标记
     */
    private boolean installSuccess;

    public LicenseVerify(String subject, String publicAlias, String storePass, String licensePath, String publicKeysStorePath) {
        this.subject = subject;
        this.publicAlias = publicAlias;
        this.storePass = storePass;
        this.licensePath = licensePath;
        this.publicKeysStorePath = publicKeysStorePath;
    }

    /**
     * 安装 License 证书，读取证书相关的信息, 在 Bean 加入容器的时候自动调用
     */
    public void installLicense() {
        this.getServerInfos("");
        try {
            Preferences preferences = Preferences.userNodeForPackage(LicenseVerify.class);

            CipherParam cipherParam = new DefaultCipherParam(storePass);

            KeyStoreParam publicStoreParam = new CustomKeyStoreParam(LicenseVerify.class,
                    publicKeysStorePath,
                    publicAlias,
                    storePass,
                    null);
            LicenseParam licenseParam = new DefaultLicenseParam(subject, preferences, publicStoreParam, cipherParam);

            licenseManager = new CustomLicenseManager(licenseParam);
            licenseManager.uninstall();
            LicenseContent licenseContent = licenseManager.install(new File(licensePath));
            DateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            installSuccess = true;
            logger.info("证书安装成功，证书有效期：{} - {}", format.format(licenseContent.getNotBefore()), format.format(licenseContent.getNotAfter()));
        } catch (Exception e) {
            installSuccess = false;
            throw new RuntimeException("证书安装失败：", e);
        }
    }

    /**
     * 卸载证书，在 Bean 从容器移除的时候自动调用
     */
    public void unInstallLicense() {
        if (installSuccess) {
            try {
                licenseManager.uninstall();
            } catch (Exception e) {
                throw new RuntimeException("证书卸载失败：", e);
            }
        }
    }

    public void getServerInfos(String osName) {
        try {
            if (StringUtils.isEmpty(osName)) {
                osName = System.getProperty("os.name");
            }
            osName = osName.toLowerCase();
            Server abstractServerInfos = null;
            //根据不同操作系统类型选择不同的数据获取方法
            if (osName.startsWith("windows")) {
                abstractServerInfos = new WindowsServer();
            } else if (osName.startsWith("linux")) {
                abstractServerInfos = new LinuxServer();
            } else {//其他服务器类型
                abstractServerInfos = new LinuxServer();
            }
            logger.info("当前服务器配置信息:{}", abstractServerInfos.getServerInfos().toString());

        } catch (Exception e) {
            logger.warn("未获取到当前服务器配置信息");
        }
    }

    public boolean verify() {
        try {
            LicenseContent licenseContent = licenseManager.verify();
            DateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            logger.info("证书有效期：{} - {}", format.format(licenseContent.getNotBefore()), format.format(licenseContent.getNotAfter()));
            return true;
        } catch (Exception e) {
            logger.error("证书校验失败：", e);
            return false;
        }
    }
}
